package tc.jv.task4;

import java.util.Locale;

import tc.jv.task9.IncompatibleVectorSizeException;

public class ArrayVector extends AbstractVector implements Cloneable
{
	
	private static final long serialVersionUID = 8392893748756664192L;
	
	protected double data[];
	
	// CONSTRUCTORS

	public ArrayVector()
	{
		data = new double[0];
	}
	
	public ArrayVector(int size)
	{
		data = new double[size];
	}
	
	// ACCESSORS
	
	@Override
	public int size()
	{
		return data.length;
	}

	@Override
	public double get(int index)
	{
		indexCheck(index);
		
		return data[index];
	}
	
	@Override
	public double set(int index, double value)
	{
		indexCheck(index);
		double oldValue = data[index]; 
		data[index] = value;
		return oldValue;
	}
	
	// SUPERCLASS METHODS
	
	// TODO Clone
	@Override
	public Object clone()
	{
		ArrayVector v = null;
		v = (ArrayVector) super.clone();
		v.data = this.data.clone();
		return v;
	}
	
	@Override
	public boolean equals(Object obj)
	{
		if (obj == this)
			return true;
		if (obj instanceof ArrayVector)
		{
			ArrayVector v = (ArrayVector) obj;
			if (this.data.length == v.data.length)
			{
				boolean e = true;
				
				for (int i = 0; e == true && i < data.length; i++)
					e &= (data[i] == v.data[i]);
				
				return e;
			}				
			else
				return false;
		}
		else if (obj instanceof Vector)
		{
			Vector v = (Vector) obj;
			if (this.data.length == v.size())
			{	
				boolean e = true;
	
				for (int i = 0; e == true && i < data.length; i++)
					e &= (data[i] == v.get(i));
				
				return e;
			}				
			else
				return false;
		}
		else
			return false;
	}

	@Override
	public int hashCode()
	{
		long lhc = 0;
		
		for (double d : data)
			lhc ^= (long) d;
		
		int hc = (int) (lhc >> 32) ^ (int) lhc;
		
		return hc;		
	}
	
	// METHODS
	
	protected String formAString(String format)
	{
		String s = "";
		for (Double d : data)
			s = s + String.format(Locale.US, format, d);
		return s;
	}

	@Override
	public void addFirst(double value)
	{
		double[] oldData = data;
		data = new double[oldData.length+1];
		data[0] = value;
		System.arraycopy(oldData, 0, data, 1, oldData.length);
	}

	@Override
	public void addLast(double value)
	{
		double[] oldData = data;
		data = new double[oldData.length+1];
		System.arraycopy(oldData, 0, data, 0, oldData.length);
		data[data.length-1] = value;
	}

	@Override
	public void add(double value)
	{
		addLast(value);
	}

	@Override
	public boolean add(int index, double value)
	{
		indexCheck(index);
		
		double[] oldData = data;
		data = new double[oldData.length+1];
		System.arraycopy(oldData, 0, data, 0, index);
		data[index] = value;
		System.arraycopy(oldData, index, data, index+1, oldData.length-index);
		
		return true;
	}

	@Override
	public double remove(int index)
	{
		indexCheck(index);

		double oldValue = data[index];
		
		double[] oldData = data;
		data = new double[oldData.length-1];
		System.arraycopy(oldData, 0, data, 0, index);
		System.arraycopy(oldData, index+1, data, index, data.length-index);
		
		return oldValue;
	}

	@Override
	public boolean fill(double[] array) throws IncompatibleVectorSizeException
	{
		return fill(array, 0);
	}
	
	@Override
	public boolean fill(double[] array, int position) throws IncompatibleVectorSizeException
	{
		vectorArgumentCheck(array, position);
		
		System.arraycopy(array, 0, data, position, array.length);
		return true;
	}
	
	@Override
	public boolean fill(Vector v) throws IncompatibleVectorSizeException
	{
		return fill(v, 0);
	}
	
	@Override
	public boolean fill(Vector v, int position) throws IncompatibleVectorSizeException
	{
		vectorArgumentCheck(v, position);
		
		if (v instanceof ArrayVector)
		{
			ArrayVector av = (ArrayVector) v;
			System.arraycopy(av.data, 0, data, position, av.data.length);
		}
		else
			for (int i = 0; i < v.size(); i++)
				data[position+i] = v.get(i);
		
		return true;
	}

	@Override
	public boolean sum(Vector v) throws IncompatibleVectorSizeException
	{
		return sum(v, 0);
	}
	
	@Override
	public boolean sum(Vector v, int position) throws IncompatibleVectorSizeException
	{
		vectorArgumentCheck(v, position);
		
		if (v instanceof ArrayVector)
		{
			ArrayVector av = (ArrayVector) v;
			for (int i = 0; i < av.data.length; i++)
				data[position+i] += av.data[i];
		}
		else
			for (int i = 0; i < v.size(); i++)
				data[position+i] += v.get(i);
		
		return true;
	}
	
	@Override
	public boolean multiply(double multiplicator)
	{
		multiplicatorCheck(multiplicator);
		
		for (int i = 0; i < data.length; i++)
			data[i] *= multiplicator;
		
		return true;
	}
	
}
